package com.siyoumi.service.wx;

import com.siyoumi.component.XApp;
import com.siyoumi.component.XJwt;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.config.SysConfig;
import com.siyoumi.entity.*;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.modules.fun.service.SvcFun;
import com.siyoumi.modules.user.service.SvcSysUser;
import com.siyoumi.modules.user.vo.SysUserAdd;
import com.siyoumi.modules.user.vo.SysUserAudit;
import com.siyoumi.service.entity.AesKi;
import com.siyoumi.service.entity.GetTokenData;
import com.siyoumi.service.vo.VoLogin;
import com.siyoumi.service.vo.VoPhoneLogin;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import org.apache.commons.collections4.map.LinkedMap;

import java.util.List;

//微信api
public interface WxApiService {
    static WxApiService getBean() {
        return getBean("wx_app");
    }

    static WxApiService getBean(String type) {
        WxApiService app = null;
        switch (type) {
            case "wx":
                app = XSpringContext.getBean(WxApiServiceMpImpl.class);
                break;
            case "wx_app":
                app = XSpringContext.getBean(WxApiServiceWxAppImpl.class);
                break;
        }

        return app;
    }

    default XReturn loginReturnData(GetTokenData tokenData) {
        SysAccsuperConfig entityConfig = SysAccsuperConfigService.getBean().getXConfig(tokenData.getX(), true);

        String ki = entityConfig.getAconfig_token(); //可能要改成随机生成
        String token = getToken(tokenData);

        //前端返回参数
        XReturn r = XReturn.getR(0);

        r.setData("x", tokenData.getX());
        r.setData("uid", tokenData.getUid()); //空：未登陆
        r.setData("openid", tokenData.getOpenid());
        r.setData("token", token);
        if (XStr.hasAnyText(tokenData.getOpenid())) { //兼容旧数据
            r.setData("wxuser_nickName", "");
            r.setData("wxuser_headimgurl", "");
        }
        if (XStr.hasAnyText(tokenData.getUid())) { //用户头像名称
            SysUser entityUser = SvcSysUser.getApp().loadEntity(tokenData.getUid());
            r.setData("user_name", entityUser.getUser_name());
            r.setData("user_headimg", entityUser.getUser_headimg());

            AesKi aesKi = AesKi.of(ki);
            r.setData("user_phone", aesKi.encTxt(entityUser.getUser_phone()));
            //积分
            r.setData("fun", SvcFun.getBean().getFun(entityUser.getUser_id()));
        }
        r.setData("ki", ki);

        LinkedMap<String, Object> mapAppend = new LinkedMap();
        mapAppend.put("fun_name", entityConfig.getAconfig_fun_name());
        mapAppend.put("img_root", SysConfig.getIns().getImgRoot());
        mapAppend.put("test", entityConfig.getAconfig_test());
        mapAppend.put("v", XDate.toMs() / 60);

        mapAppend.put("reset_oauth", false);
        r.setData("append_data", mapAppend);

        return r;
    }

    /**
     * 登陆成功统一返回参数
     *
     * @param entityWxUser
     * @param entityConfig
     */
    default XReturn loginReturnDataWx(WxUser entityWxUser, SysAccsuperConfig entityConfig) {
        GetTokenData data = GetTokenData.of("", entityConfig.getX(), entityWxUser.getWxuser_openid());
        WxUserLogin entityLogin = SvcSysUser.getBean().getLogin(entityWxUser.getWxuser_openid());
        Boolean isPhoneLogin = SvcSysUser.getBean().isLogin(entityLogin);
        if (isPhoneLogin) {
            //已登陆
            data.setUid(entityLogin.getWulogin_uid());
        }
        return loginReturnData(data);
    }

    /**
     * 登陆
     *
     * @param data
     */
    XReturn login(VoLogin data);


    /**
     * 手机登陆
     *
     * @param vo
     */
    default XReturn phoneLogin(VoPhoneLogin vo) {
        XValidator.checkTransaction();

        if (XStr.isNullOrEmpty(vo.getOpenid()) && XStr.isNullOrEmpty(vo.getUkey())) {
            return EnumSys.MISS_VAL.getR("缺少登陆密码");
        }

        SysUser entityUser;
        if (vo.getLogin_type() == 0) { //手机号
            String phone = vo.getPhone();
            if (XStr.hasAnyText(vo.getPhone_enc()) && !SysConfig.getBean().isDev()) {
                SysAccsuperConfig entityConfig = XHttpContext.getXConfig();
                AesKi aesKi = AesKi.of(entityConfig.getAconfig_token());
                phone = aesKi.decTxt(vo.getPhone_enc(), false);
                if (XStr.isNullOrEmpty(phone)) {
                    return EnumSys.ERR_VAL.getR("手机号非法");
                }
            }
            entityUser = SvcSysUser.getBean().getUserByPhone(phone);
        } else { //帐号
            vo.setAuto_reg(false); //帐号登陆，不能创建帐号
            entityUser = SvcSysUser.getBean().getUserByUsername(vo.getPhone());
        }

        if (entityUser == null) {
            if (vo.getAuto_reg()) {
                entityUser = SvcSysUser.getBean().getOrNew(SysUserAdd.of(vo.getPhone(), ""));
                //审核通过
                SysUserAudit audit = new SysUserAudit();
                audit.setIds(List.of(entityUser.getUser_id()));
                audit.setEnable(1);
                SvcSysUser.getBean().audit(audit);

                entityUser = SvcSysUser.getBean().getUserByPhone(vo.getPhone());
            }
        }
        if (entityUser == null) {
            String errmsg = "手机号未注册";
            if (vo.getLogin_type() == 1) {
                errmsg = "帐号不存在";
            }
            return XReturn.getR(20189, errmsg);
        }

        XValidator.err(SvcSysUser.getBean().valid(entityUser));

        if (XStr.hasAnyText(vo.getOpenid())) {
            WxUserLogin entitylogin = SvcSysUser.getBean().getLogin(vo.getOpenid());
            boolean updateLogin = true;
            if (entitylogin != null) {
                if (entitylogin.getWulogin_state() == 1 && entitylogin.getWulogin_uid().equals(entityUser.getUser_id())) {
                    //手机号登陆中，无需更新
                    updateLogin = false;
                }
            }

            if (updateLogin) {
                SvcSysUser.getBean().updateLoginState0(vo.getOpenid(), null);
                SvcSysUser.getBean().updateLoginState0(null, entityUser.getUser_id());

                WxUserLogin entityLoginUpdate = new WxUserLogin();
                entityLoginUpdate.setWulogin_uid(entityUser.getUser_id());
                entityLoginUpdate.setWulogin_x_id(XHttpContext.getX());
                entityLoginUpdate.setWulogin_openid(vo.getOpenid());
                entityLoginUpdate.setWulogin_state(1);
                entityLoginUpdate.setWulogin_state_date(XDate.now());
                WxUserLoginService.getBean().saveOrUpdatePassEqualField(entitylogin, entityLoginUpdate);
            }

            //更新openid
            SysUser entityUserUpdate = new SysUser();
            entityUserUpdate.setUser_openid(vo.getOpenid());
            SvcSysUser.getApp().saveOrUpdatePassEqualField(entityUser, entityUserUpdate);
            SvcSysUser.getApp().delEntityCache(entityUser.getKey());
        } else {
            String encPwd = XApp.encPwd(entityUser.getUser_x_id(), vo.getDecPwd());
            if (!entityUser.getUser_pwd().equals(encPwd)) {
                return EnumSys.PWD_ERR.getR("登陆密码错误");
            }
        }

        GetTokenData data = GetTokenData.of(entityUser.getUser_id(), XHttpContext.getX(), vo.getOpenid());
        return loginReturnData(data);
    }

    /**
     * 退出登陆
     *
     * @param openid
     */
    default XReturn phoneLogout(String openid) {
        SvcSysUser.getBean().updateLoginState0(openid, null);

        return EnumSys.OK.getR();
    }

    /**
     * 扫码登陆设置openid
     */
    XReturn loginSetOpenid(String token);

    /**
     * 获取手机号
     *
     * @param data
     */
    XReturn getPhone(String data);


    default String getToken(GetTokenData data) {
        XReturn tokenData = XReturn.getR(0);
        tokenData.setData("timestamp", data.getTimestamp());
        tokenData.setData("x", data.getX());
        tokenData.setData("uid", data.getUid());
        tokenData.setData("openid", data.getOpenid());

        XJwt jwt = XJwt.getBean();
        return jwt.getToken(tokenData, data.getExpireSecond());
    }

    /**
     * 登陆成功获取token
     * 请求需要携带
     *
     * @return token
     */
    default String getToken(XReturn r) {
        Integer expireSecond = 3600 * 12;
        XJwt jwt = XJwt.getBean();

        return jwt.getToken(r, expireSecond);
    }
}
